package org.snail.transport;

import com.google.common.reflect.Reflection;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import io.netty.channel.Channel;
import org.snail.SnailServer;
import org.snail.core.ServiceMetadata;
import org.snail.serialization.SerializerFactory;
import org.snail.transport.protocol.*;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.Executors;

/**
 * 服务端处理客户端请求过来的调用。
 *
 * Created by fish on 17/8/26.
 */
public class AcceptorDispatcher {


    private ListeningExecutorService service;

    public AcceptorDispatcher(){
        service = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
    }


    public void dispatch(Channel channel,Message message){
        service.submit(new DispatcherRunnable(channel,message));
    }


    private class DispatcherRunnable implements Runnable{

        private Channel channel;

        private Message message;

        public DispatcherRunnable(Channel channel, Message message){
            this.channel = channel;
            this.message = message;
        }

        @Override
        public void run() {

            Header header = message.getHeader();
            byte[] body = message.getBody();
            Request request = SerializerFactory.getDefaultSerializer().readObject(body,Request.class);

            //TEST
            ServiceMetadata metadata = new ServiceMetadata(request.getGroup(),request.getServiceProviderName(),request.getVersion());

            Object objectService = SnailServer.getInstance().getServiceClazz(metadata);


            Class<?> clazz =  objectService.getClass();

            Object result = null;

            try {
                Method method = clazz.getMethod(request.getMethodName(),request.getReturnType());
                result =  method.invoke(objectService,request.getArgs());
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

            Response response = new Response();
            response.setResult(result);

            byte[] responseBody = SerializerFactory.getDefaultSerializer().writeObject(response);
            //只需重写header响应类型和长度。
            header.setMessageType(MessageType.RESPONSE);
            Message responseMessage = new Message(header,responseBody);
            channel.writeAndFlush(responseMessage);

        }
    }



}
